/**
 * Copyright (c) 2021 OceanBase
 * OceanBase CE is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#define USING_LOG_PREFIX SERVER
#include "sql/resolver/ddl/ob_alter_tablegroup_resolver.h"
#include "sql/resolver/ddl/ob_tablegroup_resolver.h"
#include "share/ob_define.h"
#include "share/ob_rpc_struct.h"
#include "sql/session/ob_sql_session_info.h"


namespace oceanbase
{
using namespace share::schema;
using namespace common;

namespace sql
{

using share::schema::AlterColumnSchema;

ObAlterTablegroupResolver::ObAlterTablegroupResolver(ObResolverParams &params)
    : ObTableGroupResolver(params)
{
}

ObAlterTablegroupResolver::~ObAlterTablegroupResolver()
{
}

int ObAlterTablegroupResolver::resolve(const ParseNode &parser_tree)
{
  int ret = OB_SUCCESS;
  ParseNode *node = const_cast<ParseNode*>(&parser_tree);
  if (OB_ISNULL(session_info_) || OB_ISNULL(node) ||
      T_ALTER_TABLEGROUP != node->type_ || OB_ISNULL(node->children_)) {
    ret = OB_ERR_UNEXPECTED;
    LOG_WARN("session_info_ is null or parser error", K(ret));
  }
  ObAlterTablegroupStmt *alter_tablegroup_stmt = NULL;
  if (OB_SUCC(ret)) {
    //create alter table stmt
    if (NULL == (alter_tablegroup_stmt = create_stmt<ObAlterTablegroupStmt>())) {
      ret = OB_ALLOCATE_MEMORY_FAILED;
      LOG_ERROR("failed to create alter table stmt", K(ret));
    } else {
      stmt_ = alter_tablegroup_stmt;
    }

    if (OB_SUCC(ret)) {
      if (NULL != node->children_[TG_NAME] && T_IDENT == node->children_[TG_NAME]->type_) {
        ObString tablegroup_name;
        tablegroup_name.assign_ptr(node->children_[TG_NAME]->str_value_,
                                   static_cast<int32_t>(node->children_[TG_NAME]->str_len_));
        alter_tablegroup_stmt->set_tenant_id(session_info_->get_effective_tenant_id());
        alter_tablegroup_stmt->set_tablegroup_name(tablegroup_name);
      } else {
        ret = OB_ERR_UNEXPECTED;
        LOG_WARN("node is null or node type is not T_IDENT", K(ret));
      }
    }
    if (OB_FAIL(ret)) {
    } else if (OB_ISNULL(node->children_[1])) {
      ret = OB_ERR_UNEXPECTED;
      LOG_WARN("node is null", K(ret));
    } else if (T_TABLE_LIST == node->children_[1]->type_) {
      ParseNode *table_list_node = node->children_[TABLE_LIST];
      for(int32_t i = 0; OB_SUCC(ret) && i < table_list_node->num_child_; ++i) {
        ParseNode *relation_node = table_list_node->children_[i];
        if (NULL != relation_node) {
          ObString table_name;
          ObString database_name;
          obrpc::ObTableItem table_item;
          if (OB_FAIL(resolve_table_relation_node(relation_node,
                                                  table_name,
                                                  database_name))) {
            LOG_WARN("failed to resolve table name", K(ret), K(table_item));
          } else {
            table_item.table_name_ = table_name;
            table_item.database_name_ = database_name;
            if (OB_FAIL(alter_tablegroup_stmt->add_table_item(table_item))) {
              LOG_WARN("failed to add table item!", K(ret), K(table_item));
            }
          }
        } else {
          ret = OB_ERR_UNEXPECTED;
          LOG_WARN("node is null", K(ret));
        }
      } //end for
    } else if (T_ALTER_TABLEGROUP_ACTION_LIST == node->children_[1]->type_) {
      if (OB_FAIL(resolve_tablegroup_option(alter_tablegroup_stmt, node->children_[1]))) {
        LOG_WARN("fail to resolve tablegroup option", K(ret));
      } else {
        alter_tablegroup_stmt->set_alter_option_set(get_alter_option_bitset());
      }
    } else if (T_ALTER_PARTITION_OPTION == node->children_[1]->type_) {
      if (OB_FAIL(resolve_partition_options(*(node->children_[1])))) {
        LOG_WARN("fail to resolve tablegroup partition option", K(ret));
      } else {
        // partition_array是否序列化依赖part_level，由于resolver端不获取schema，
        // 为避免序列化时丢失数据，可设置part_level为PARTITION_LEVEL_ONE
        // （目前仅能动态增删一级range/range column分区）
        alter_tablegroup_stmt->get_alter_tablegroup_arg()
                .alter_tablegroup_schema_.set_part_level(PARTITION_LEVEL_ONE);
      }
    } else {
      ret = OB_ERR_UNEXPECTED;
      LOG_WARN("invalid node type", K(ret), K(node->children_[1]->type_));
    }
  }
  return ret;
}

int ObAlterTablegroupResolver::resolve_partition_options(const ParseNode &node)
{
  int ret = OB_SUCCESS;
  if (OB_UNLIKELY(T_ALTER_PARTITION_OPTION != node.type_
                  || 0 >= node.num_child_
                  || OB_ISNULL(node.children_)
                  || OB_ISNULL(node.children_[0]))) {
    ret = OB_ERR_UNEXPECTED;
    SQL_RESV_LOG(WARN, "invalid parse tree!", K(ret));
  } else if (OB_ISNULL(session_info_)) {
    ret = OB_ERR_UNEXPECTED;
    LOG_WARN("session info is null", K(ret));
  } else {
    ObAlterTablegroupStmt *alter_tablegroup_stmt = get_alter_tablegroup_stmt();
    if (OB_SUCC(ret)) {
      obrpc::ObAlterTablegroupArg &arg = alter_tablegroup_stmt->get_alter_tablegroup_arg();
      switch(node.children_[0]->type_) {
      case T_ALTER_PARTITION_ADD: {
          ParseNode *partition_node = node.children_[0];
          if (OB_FAIL(resolve_add_partition(*partition_node))) {
            SQL_RESV_LOG(WARN, "Resolve add partition error!", K(ret));
          } else if (OB_FAIL(arg.alter_option_bitset_.add_member(obrpc::ObAlterTablegroupArg::ADD_PARTITION))) {
            LOG_WARN("failed to add member", K(ret));
          }
          break;
        }
      case T_ALTER_PARTITION_DROP: {
          ParseNode *partition_node = node.children_[0];
          if (OB_FAIL(resolve_drop_partition(*partition_node))) {
            SQL_RESV_LOG(WARN, "Resolve drop partition error!", K(ret));
          } else if (OB_FAIL(arg.alter_option_bitset_.add_member(obrpc::ObAlterTablegroupArg::DROP_PARTITION))) {
            LOG_WARN("failed to add member", K(ret));
          }
          break;
        }
      case T_ALTER_PARTITION_PARTITIONED:
        {
          ParseNode *partition_node = node.children_[0];
          bool enable_split_partition = false;
          if (OB_ISNULL(partition_node)
              || 1 != partition_node->num_child_
              || OB_ISNULL(partition_node->children_[0])) {
            ret = OB_INVALID_ARGUMENT;
            SQL_RESV_LOG(WARN, "invalid partition node", K(ret), K(partition_node));
          } else if (OB_FAIL(get_enable_split_partition(session_info_->get_effective_tenant_id(),
                                                        enable_split_partition))) {
            LOG_WARN("failed to get enable split partition config", K(ret),
                "tenant_id", session_info_->get_effective_tenant_id());
          } else if (!enable_split_partition) {
            ret = OB_OP_NOT_ALLOW;
            LOG_WARN("partitioned table not allow", K(ret));
            LOG_USER_ERROR(OB_OP_NOT_ALLOW, "partition table");
          } else if (OB_FAIL(resolve_partition_table_option(alter_tablegroup_stmt,
                                                            partition_node->children_[0],
                                                            arg.alter_tablegroup_schema_))) {
            LOG_WARN("fail to resolve partition node", K(ret), K(partition_node));
          } else if (OB_FAIL(arg.alter_option_bitset_.add_member(obrpc::ObAlterTablegroupArg::PARTITIONED_TABLE))) {
            LOG_WARN("failed to add member", K(ret));
          }
          break;
        }
      case T_ALTER_PARTITION_REORGANIZE:
        {
          ParseNode *partition_node = node.children_[0];
          bool enable_split_partition = false;
          if (OB_ISNULL(partition_node)
              || 2 != partition_node->num_child_
              || OB_ISNULL(partition_node->children_[0])
              || OB_ISNULL(partition_node->children_[1])) {
            ret = OB_INVALID_ARGUMENT;
            SQL_RESV_LOG(WARN, "invalid partition node", K(ret), K(partition_node));
          } else if (OB_FAIL(get_enable_split_partition(session_info_->get_effective_tenant_id(),
                                                        enable_split_partition))) {
            LOG_WARN("failed to get enable split partition config", K(ret),
                "tenant_id", session_info_->get_effective_tenant_id());
          } else if (!enable_split_partition) {
            ret = OB_OP_NOT_ALLOW;
            LOG_WARN("reorganize partition not allow", K(ret));
            LOG_USER_ERROR(OB_OP_NOT_ALLOW, "reorganize partition");
          } else if (OB_FAIL(resolve_reorganize_partition(*partition_node))) {
            LOG_WARN("failed to reorganize partition", K(ret));
          } else if (OB_FAIL(arg.alter_option_bitset_.add_member(obrpc::ObAlterTablegroupArg::REORGANIZE_PARTITION))) {
            LOG_WARN("failed to add member", K(ret));
          }
          break;
        }
      case T_ALTER_PARTITION_SPLIT:
        {
          ParseNode *partition_node = node.children_[0];
          bool enable_split_partition = false;
          if (OB_ISNULL(partition_node)
              || 2 != partition_node->num_child_
              || OB_ISNULL(partition_node->children_[0])
              || OB_ISNULL(partition_node->children_[1])) {
            ret = OB_INVALID_ARGUMENT;
            SQL_RESV_LOG(WARN, "invalid partition node", K(ret), K(partition_node));
          } else if (OB_FAIL(get_enable_split_partition(session_info_->get_effective_tenant_id(),
                                                        enable_split_partition))) {
            LOG_WARN("failed to get enable split partition config", K(ret),
                "tenant_id", session_info_->get_effective_tenant_id());
          } else if (!enable_split_partition) {
            ret = OB_OP_NOT_ALLOW;
            LOG_WARN("split partition not allow", K(ret));
            LOG_USER_ERROR(OB_OP_NOT_ALLOW, "split partition");
          } else if (OB_FAIL(resolve_split_partition(*partition_node))) {
            LOG_WARN("failed to reorganize partition", K(ret));
          } else if (OB_FAIL(arg.alter_option_bitset_.add_member(obrpc::ObAlterTablegroupArg::SPLIT_PARTITION))) {
            LOG_WARN("failed to add member", K(ret));
          }
          break;
        }
      default: {
          ret = OB_ERR_UNEXPECTED;
          SQL_RESV_LOG(WARN, "Unknown alter partition option %d!",
                       "option type", node.children_[0]->type_, K(ret));
          break;
        }
      }
    }
  }
  return ret;
}

int ObAlterTablegroupResolver::resolve_add_partition(const ParseNode &node)
{
  int ret = OB_SUCCESS;
  int64_t expr_num = OB_INVALID_INDEX;
  ParseNode *range_part_elements_node = NULL;
  PartitionInfo part_info;
  bool in_tablegroup = true;
  ObAlterTablegroupStmt *alter_tablegroup_stmt = get_alter_tablegroup_stmt();
  const ObTablegroupSchema *tablegroup_schema = NULL;
  if (OB_ISNULL(schema_checker_)
      || OB_ISNULL(alter_tablegroup_stmt)
      || OB_ISNULL(node.children_[0])) {
    ret = OB_ERR_UNEXPECTED;
    LOG_WARN("invalid schema, stmt or node ", K(ret), KP(schema_checker_), KP(alter_tablegroup_stmt), 
             "node", node.children_[0]);
  } else if (OB_FAIL(schema_checker_->get_tablegroup_schema(session_info_->get_effective_tenant_id(),
                                                            alter_tablegroup_stmt->get_tablegroup_name(),
                                                            tablegroup_schema))) {      
    LOG_WARN("fail to get tablegroup schema", K(ret));
  } else if (OB_ISNULL(tablegroup_schema)) {
    ret = OB_TABLEGROUP_NOT_EXIST;
    LOG_WARN("invalid tablegroup schema", K(ret));
  } else if (OB_ISNULL(range_part_elements_node = node.children_[0]->children_[0])) {
    ret = OB_ERR_UNEXPECTED;
    LOG_WARN("NULL ptr", K(ret));
  } else if (tablegroup_schema->is_range_part()) {
      // resolver端放宽对value类型的检查，由rs端检查range分区的value是否为int
    const ObPartitionFuncType part_type = ObPartitionFuncType::PARTITION_FUNC_TYPE_RANGE_COLUMNS;
  // 此处expr_num由resolver解析所得，不代表tablegroup实际的expr_num
    if (OB_FAIL(resolve_range_partition_elements(range_part_elements_node,
                                                false, // is_subpartition
                                                part_type,
                                                part_info.range_value_exprs_,
                                                part_info.parts_,
                                                part_info.subparts_,
                                                expr_num,
                                                in_tablegroup))) {
      LOG_WARN("resolve range partition elements fail", K(ret));
    } else if (OB_FAIL(alter_tablegroup_stmt->get_part_values_exprs().assign(
      part_info.range_value_exprs_))) {
      LOG_WARN("assign faield", K(ret));
    }
  } else if (tablegroup_schema->is_list_part()) {
    const ObPartitionFuncType part_type = ObPartitionFuncType::PARTITION_FUNC_TYPE_LIST_COLUMNS;
    if (OB_FAIL(resolve_list_partition_elements(range_part_elements_node,
                                                false,
                                                part_type,
                                                expr_num,
                                                part_info.list_value_exprs_,
                                                part_info.parts_,
                                                part_info.subparts_,
                                                in_tablegroup))) {
      LOG_WARN("resolve list partition elememts fail", K(ret));
    }  else if (OB_FAIL(alter_tablegroup_stmt->get_part_values_exprs().assign(part_info.list_value_exprs_))) {
      LOG_WARN("assign list values failed", K(ret));
    }
  }
  if (OB_FAIL(ret)) {

  } else {
    share::schema::ObPartition *part = NULL;
    ObTablegroupSchema &alter_tablegroup_schema =
        get_alter_tablegroup_stmt()->get_alter_tablegroup_arg().alter_tablegroup_schema_;
    for (int64_t i = 0; OB_SUCC(ret) && i < part_info.parts_.count(); ++i) {
      part = &(part_info.parts_.at(i));
      if (!part->get_part_name().empty()) {
        if (OB_FAIL(alter_tablegroup_schema.check_part_name(*part))) {
          LOG_WARN("check part name failed", K(ret));
        }
      }
      if (OB_FAIL(ret)) {
      } else if (OB_FAIL(alter_tablegroup_schema.add_partition(*part))) {
        LOG_WARN("add partition failed", K(ret));
      }
    }
    if (OB_SUCC(ret)) {
      alter_tablegroup_stmt->set_part_func_expr_num(expr_num);
      alter_tablegroup_schema.get_part_option().set_part_func_type(tablegroup_schema->get_part_option().get_part_func_type());
      alter_tablegroup_schema.get_part_option().set_part_num(alter_tablegroup_schema.get_partition_num());
    }
  }
  return ret;
}

int ObAlterTablegroupResolver::resolve_drop_partition(const ParseNode &node)
{
  int ret = OB_SUCCESS;
  if (OB_ISNULL(node.children_)
      || (T_ALTER_PARTITION_DROP != node.type_
          && T_ALTER_PARTITION_TRUNCATE != node.type_ )) {
    ret = OB_ERR_UNEXPECTED;
    SQL_RESV_LOG(WARN, "invalid parse tree", K(ret), "type", node.type_);
  } else {
    const ParseNode *name_list = node.children_[0];
    if (OB_ISNULL(name_list)) {
      ret = OB_ERR_UNEXPECTED;
      SQL_RESV_LOG(WARN, "invalid parse tree", K(ret));
    } else {
      ObAlterTablegroupStmt *alter_tablegroup_stmt = get_alter_tablegroup_stmt();
      if (OB_ISNULL(alter_tablegroup_stmt)) {
        ret = OB_ERR_UNEXPECTED;
        SQL_RESV_LOG(WARN, "alter tablegroup stmt should not be null", K(ret));
      }
      ObTablegroupSchema &alter_tablegroup_schema =
          alter_tablegroup_stmt->get_alter_tablegroup_arg().alter_tablegroup_schema_;
      for (int64_t i = 0; OB_SUCC(ret) && i < name_list->num_child_; ++i) {
        ObPartition part;
        ObString partition_name(static_cast<int32_t>(name_list->children_[i]->str_len_),
            name_list->children_[i]->str_value_);
        if (OB_FAIL(part.set_part_name(partition_name))) {
          ret = OB_ALLOCATE_MEMORY_FAILED;
          SQL_RESV_LOG(ERROR, "set partition name failed", K(partition_name), K(ret));
        } else if (OB_FAIL(alter_tablegroup_schema.check_part_name(part))){
          SQL_RESV_LOG(WARN, "check part name failed!", K(part), K(ret));
        } else if (OB_FAIL(alter_tablegroup_schema.add_partition(part))){
          SQL_RESV_LOG(WARN, "add partition failed!", K(part), K(ret));
        }
      }
    }
  }
  return ret;
}

int ObAlterTablegroupResolver::resolve_reorganize_partition(const ParseNode &node)
{
  int ret = OB_SUCCESS;
  ObAlterTablegroupStmt *alter_tablegroup_stmt = get_alter_tablegroup_stmt();
  if (T_ALTER_PARTITION_REORGANIZE != node.type_
    || 2 != node.num_child_
    || OB_ISNULL(node.children_[0])
    || OB_ISNULL(node.children_[1])
    || OB_ISNULL(alter_tablegroup_stmt)) {
    ret = OB_INVALID_ARGUMENT;
    LOG_WARN("invalid arguement", K(ret), "children num", node.num_child_,
    "children[0]", node.children_[0], "children[1]", node.children_[1]);
  } else {
    ObTablegroupSchema &alter_tablegroup_schema = alter_tablegroup_stmt->get_alter_tablegroup_arg().alter_tablegroup_schema_;
    ParseNode *name_list = node.children_[1];
    if (OB_ISNULL(name_list)) {
      ret = OB_INVALID_ARGUMENT;
      LOG_WARN("invalid argument", K(ret), K(name_list));
    } else if (1 != name_list->num_child_) {
      ret = OB_NOT_SUPPORTED;
      LOG_WARN("alter tablegroup reorganize multi partition not supported now", K(ret));
      LOG_USER_ERROR(OB_NOT_SUPPORTED, "alter tablegroup reorganize multiple partitions");
    } else if (OB_NOT_NULL(name_list->children_[0])) {
      ObPartition part;
      ObString partition_name(static_cast<int32_t>(name_list->children_[0]->str_len_),
                              name_list->children_[0]->str_value_);
      if (OB_FAIL(alter_tablegroup_schema.set_split_partition(partition_name))) {
        LOG_WARN("failed to set split partition name", K(ret));
      }
    } else {
      ret = OB_ERR_UNEXPECTED;
      LOG_WARN("name list can not be null", K(ret), K(name_list));
    }
    if (OB_FAIL(ret)) {
      //nothing
    } else if (OB_FAIL(resolve_add_partition(node))) {
      LOG_WARN("failed resolve add partition", K(ret));
    } else if (1 == alter_tablegroup_schema.get_partition_num()) {
      ret = OB_ERR_SPLIT_INTO_ONE_PARTITION;
      LOG_USER_ERROR(OB_ERR_SPLIT_INTO_ONE_PARTITION);
      LOG_WARN("can not split partition into one partition", K(ret), K(alter_tablegroup_schema));
    }
  }
  return ret;
}

int ObAlterTablegroupResolver::resolve_split_partition(const ParseNode &node)
{
  int ret = OB_SUCCESS;
  ObAlterTablegroupStmt *alter_tablegroup_stmt = get_alter_tablegroup_stmt();
  const ObTablegroupSchema *tablegroup_schema = NULL;
  if (OB_ISNULL(schema_checker_)) {
    ret = OB_ERR_UNEXPECTED;
    LOG_WARN("invalid schema check", K(ret));
  } else if (OB_FAIL(schema_checker_->get_tablegroup_schema(session_info_->get_effective_tenant_id(),
                                                            alter_tablegroup_stmt->get_tablegroup_name(),
                                                            tablegroup_schema))) {
    LOG_WARN("fail to get tablegroup schema", K(ret));
  } else if (OB_ISNULL(tablegroup_schema)) {
    ret = OB_TABLEGROUP_NOT_EXIST;
    LOG_WARN("invalid tablegroup schema", K(ret));
  } else if (T_ALTER_PARTITION_SPLIT != node.type_
             || 2 != node.num_child_
             || OB_ISNULL(node.children_[0])
             || OB_ISNULL(node.children_[1])
             || T_SPLIT_ACTION != node.children_[1]->type_) {
    ret = OB_INVALID_ARGUMENT;
    LOG_WARN("invalid argument", K(ret), "node_type", node.type_,
             "node_num", node.num_child_);
  } else if (OB_ISNULL(alter_tablegroup_stmt)) {
    ret = OB_ERR_UNEXPECTED;
    LOG_WARN("alter table stmt should not be null", K(ret));
  } else {
    ParseNode *name_list = node.children_[0];
    ObTablegroupSchema &alter_tablegroup_schema =
      alter_tablegroup_stmt->get_alter_tablegroup_arg().alter_tablegroup_schema_;
    if (OB_ISNULL(name_list)) {
      ret = OB_INVALID_ARGUMENT;
      LOG_WARN("invalid argument", K(ret));
    } else {
      ObString partition_name(static_cast<int32_t>(name_list->str_len_),
                              name_list->str_value_);
      if (OB_FAIL(alter_tablegroup_schema.set_split_partition(partition_name))) {
        LOG_WARN("failed to set split partition name", K(ret));
      }
    }

    int64_t partition_count = OB_INVALID_COUNT;
    int64_t expr_value_num = OB_INVALID_COUNT;
    const ParseNode *split_node = node.children_[1];
    PartitionInfo part_info;

    if (OB_FAIL(ret)) {
      //nothing
    } else if (OB_ISNULL(split_node)) {
      ret = OB_ERR_UNEXPECTED;
      LOG_WARN("split node is null", K(ret), K(split_node));
    } else if (OB_FAIL(check_split_type_valid(split_node, 
                                              tablegroup_schema->get_part_option().get_part_func_type()))) {
      LOG_WARN("failed to check split type valid", K(ret), K(tablegroup_schema));
    } else if (OB_NOT_NULL(split_node->children_[AT_VALUES_NODE])) {
      // split at [into ()]
      partition_count = 1;
      if (OB_FAIL(resolve_split_at_partition(alter_tablegroup_stmt, 
                                             split_node,
                                             tablegroup_schema->get_part_option().get_part_func_type(),
                                             part_info.part_func_exprs_,
                                             alter_tablegroup_schema,
                                             expr_value_num,
                                             true))) {
        LOG_WARN("failed to resolve split at partition", K(ret));
      }
    } else if (OB_NOT_NULL(split_node->children_[PARTITION_DEFINE_NODE])
               && OB_NOT_NULL(split_node->children_[PARTITION_DEFINE_NODE]->children_[0])) {
      // split into ()
      ParseNode *range_element_node = split_node->children_[PARTITION_DEFINE_NODE]->children_[0];
      if (OB_FAIL(resolve_split_into_partition(alter_tablegroup_stmt, 
                                               range_element_node,
                                               tablegroup_schema->get_part_option().get_part_func_type(),
                                               part_info.part_func_exprs_,
                                               partition_count,
                                               expr_value_num, 
                                               alter_tablegroup_schema, 
                                               true))) {
        LOG_WARN("failed to resolve split at partition", K(ret));
      }
    } else {
      //不能即没有at也没有partition说明
      ret = OB_ERR_MISS_AT_VALUES;
      LOG_WARN("miss at and less than values", K(ret));
      LOG_USER_ERROR(OB_ERR_MISS_AT_VALUES);
    }

    if (OB_FAIL(ret)) {
    } else {
      alter_tablegroup_stmt->set_part_func_expr_num(expr_value_num);
      alter_tablegroup_schema.get_part_option().set_part_func_type(tablegroup_schema->get_part_option().get_part_func_type());
      alter_tablegroup_schema.get_part_option().set_part_num(partition_count);//最后一个partition可能没有最大值，需要在rs端处理
    }
  }
  return ret;
}

} //namespace common
} //namespace oceanbase
